using System;
using System.Collections.Generic;
using System.Text;
using DatabaseCode.Data;

namespace DatabaseCode.Maker
{
  class ManagerMaker
  {
    public static string OutSource(D1_Headers headers, string managername)
    {
      HashSet<D2_Header> requiredHeders;
      D2_Header h = GetHeader(headers, managername);
      string classname = h.Name;
      if (h == null)
      {
        return "（引数マネージャ名に一致したヘッダーが見つかりません。ManagerMaker）";
      }
      requiredHeders = headers.EnumRequiredHeaders(h);

      string str = h.IncludeString() + @"
#include <memory.h> // memcpy

namespace dataio {

" + classname + @"::" + classname + "()\r\n" + /*"(" + ParameterString(requiredHeders) + @")
";
      is_first = true;
      if (requiredHeders.Count > 0)
      {
        str += "  : ";
        foreach (D2_Header header in requiredHeders)
        {
          if (is_first)
          {
            is_first = false;
          }
          else
          {
            str += ", ";
          }
          str += header.ManagerMemberName + "(" + header.ManagerMemberName + ")"; 
        }
      }
      str += */
@"{
}
" + classname + @"::~" + classname + @"()
{
}

Enums::Errors " + classname + @"::Add(const Enums::" + classname + @"Table table, const void* data)
{
  switch (table)
  {
";
      foreach (D3_Table t in h.Tables)
      {
        str += "  case Enums::k" + t.Name + ":\r\n";
        str += "    return " + Utility.MemberStringWithS_(t.Name) + ".Add(*(" + t.Name + "*)data);\r\n";
      }
      str += @"  }
  return Enums::kNoneTypeError;
}
Enums::Errors " + classname + @"::Remove(const Enums::" + classname + @"Table table, const void* data)
{
  switch (table)
  {";
      foreach (D3_Table t in h.Tables)
      {
        str += "  case Enums::k" + t.Name + ":\r\n";
        str += "    return " + Utility.MemberStringWithS_(t.Name) + ".Remove(*(" + t.Name + "*)data);\r\n";
      }
      str += @"  }
  return Enums::kNoneTypeError;
}
Enums::Errors " + classname + @"::Update(const Enums::" + classname + @"Table table, const void* data)
{
";
      foreach (D3_Table t in h.Tables)
      {
        str += "  " + t.Name + "* p" + Utility.SeparateByUndercores(t.Name) + ";\r\n";
      }
      str += @"  Enums::Errors error;

  switch (table)
  {
";
      foreach (D3_Table t in h.Tables)
      {
        str += "  case Enums::k" + t.Name + ":\r\n";
        str += "    error = " + Utility.MemberStringWithS_(t.Name) + ".GetPointer(*(" +
          t.Name + "*)data, p" + Utility.SeparateByUndercores(t.Name) + ");\r\n";
        str += "    if (error != Enums::kSuccess) return error;\r\n";
        str += "    ::memcpy(p" + Utility.SeparateByUndercores(t.Name) + ", data, sizeof(" + t.Name + "));\r\n";
        str += "    return error;\r\n";
      }
      str += @"  }
  return Enums::kNoneTypeError;
}

}  //  namespace dataio";
      return str;
    }

    /* 出力例
#ifndef COMMON_MON_DATA_MANAGER_H_
#define COMMON_MON_DATA_MANAGER_H_

#include <vector>
#include "mon_data.h"
#include "dataio_base.h"
#include "base.h"

namespace dataio {

class MgrDataMgr;
class RelationShip;

class MonDataMgr
{
  friend class RelationShip;
public:
  MonDataMgr();
  ~MonDataMgr();

  Enums::Errors Add(const Enums::MonDataMgrTable table, const void* data);
  Enums::Errors Remove(const Enums::MonDataMgrTable table, const void* data);
  Enums::Errors Update(const Enums::MonDataMgrTable table, const void* data);

private:

  Table<LotNo>         lot_nos_;
  Table<Pool>          pools_;
  Table<Production>    productions_;
  Table<RedPaper>      red_papers_;

  MgrDataMgr* mgr_data_mgr_;

  DISALLOW_COPY_AND_ASSIGN(MonDataMgr);
};


}  //  namespace dataio

#endif // COMMON_MON_DATA_MANAGER_H_*/
    public static string OutHeader(D1_Headers headers, string managername)
    {
      D2_Header h = null;
      HashSet<D2_Header> requiredHeders;
      string str = "";

      h = GetHeader(headers, managername);
      if (h == null)
      {
        return "（引数マネージャ名に一致したヘッダーが見つかりません。ManagerMaker）";
      }

      requiredHeders = headers.EnumRequiredHeaders(h);

      str += h.IncludeGuardStartString() + @"
#include <vector>
#include """ + h.DataHeader + @"""
#include ""dataio_base.h""
#include ""base.h""

namespace dataio {

";
      str += DeclarationString(requiredHeders) + 
@"class RelationShip;

class " + h.Name + @"
{
" + FriendClassDeclarationString(requiredHeders) + @"
public:
  " + h.Name + @"();
  ~" + h.Name + @"();

  Enums::Errors Add(const Enums::" + managername + @"Table table, const void* data);
  Enums::Errors Remove(const Enums::" + managername + @"Table table, const void* data);
  Enums::Errors Update(const Enums::" + managername + @"Table table, const void* data);

private:
" + TableDefinitionString(h) + @"
" + ManagerDefinitionString(requiredHeders) + @"
  DISALLOW_COPY_AND_ASSIGN(" + h.Name + @");
};


}  //  namespace dataio

";
      str += h.IncludeGuardEndString();
      return str;
    }

    //ヘッダを取得する
    private static D2_Header GetHeader(D1_Headers headers, string managername)
    {
      foreach (D2_Header h in headers.Headers)
      {
        if (h.Name == managername)
        {
          return h;
        }
      }
      return null;
    }

    //クラス宣言文字列を返す。
    private static string DeclarationString(HashSet<D2_Header> list)
    {
      string str = "";

      foreach (D2_Header h in list)
      {
        str += "class " + h.Name + ";\r\n";
      }
      return str;
    }

    //クラス引数文字列を返す。
    private static string ParameterString(HashSet<D2_Header> list)
    {
      string str = "";
      bool is_first = true;

      foreach (D2_Header h in list)
      {
        if (is_first)
        {
          is_first = false;
        }
        else
        {
          str += ", ";
        }
        str += h.Name + "* " + h.Membername;
      }
      return str;
    }

    //テーブルメンバ定義文字列を返す。
    private static string TableDefinitionString(D2_Header header)
    {
      string str = "";

      foreach (D3_Table t in header.Tables)
      {
        str += Utility.InsertSpacesToRight("  Table<" + t.Name + ">", 24) +
          Utility.MemberStringWithS_(t.Name) + ";\r\n";
      }
      return str;
    }

    //マネージャクラスメンバ定義文字列を返す。
    private static string ManagerDefinitionString(HashSet<D2_Header> list)
    {
      string str = "";

      foreach (D2_Header h in list)
      {
        str += "  " + h.Name + "* " + Utility.MemberStringWithS_(h.Name) + ";\r\n";
      }
      return str;
    }

    //フレンドクラス宣言文字列を返す。
    private static string FriendClassDeclarationString(HashSet<D2_Header> list)
    {
      string str = "";

      foreach (D2_Header h in list)
      {
        str += "  friend class " + h.Name + ";\r\n";
      }
      return str + "  friend class RelationShip;\r\n";
    }
  }
}
